package com.nulldev.util.web.HttpServer3.rewrite;

import static com.nulldev.util.web.HttpServer3.rewrite.InternalImpl.readTillNextLine;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import com.nulldev.util.data.Variables;
import com.nulldev.util.io.IOUtils;
import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;
import com.nulldev.util.web.HttpServer3.extensions.http2.api_compat.HttpRequestDispatcher;
import com.nulldev.util.web.HttpServer3.extensions.http2.compat.HttpRequestValidator;
import com.nulldev.util.web.HttpServer3.extensions.http2.compat.IOContainer;
import com.nulldev.util.web.HttpServer3.extensions.http2.compat.RequestValidatorConfig;
import com.nulldev.util.web.HttpServer3.extensions.http2.util.ServerThreadUtils;
import com.nulldev.util.web.HttpServer3.pages.v3.RequestProtocolType;
import com.nulldev.util.web.HttpServer3.util.HTTPPrintWriter;

class Http2Component {

	private static final Logger log = LoggerFactory.getLogger();
	private final HttpServer3RW hs3;

	/* H2 */

	final HttpRequestDispatcher rqd;
	final HttpRequestValidator hrv = new HttpRequestValidator(new RequestValidatorConfig());

	public Http2Component(final HttpServer3RW hs3) {
		this.hs3 = Variables.requireNonNullObject(hs3, "hs3");
		this.rqd = new HttpRequestDispatcher(hs3);
	}

	protected RequestProtocolType __upgrade_to_http2(final HTTPPrintWriter out, final OutputStream os, final InputStream is, final Socket socket,
			RequestProtocolType protocol, final boolean expectHTTPS) throws Exception {
		out.println("HTTP/1.1 101 Switching Protocols");
		out.println("Connection: Upgrade");
		out.println("Upgrade: h2c");
		out.println("Server: HttpServer3 from nullUtil 3.0");
		out.println();
		out.flush();
		os.flush();
		protocol = (expectHTTPS ? RequestProtocolType.HTTPS_2_0 : RequestProtocolType.HTTP_2_0);
		is.read();
		final String _h2_header = readTillNextLine(is);
		if (!Variables.requireNonNullObject(_h2_header, "_h2_header").equals("PRI * HTTP/2.0")
				&& !Variables.requireNonNullObject(_h2_header, "_h2_header").equals("RI * HTTP/2.0")) {
			log.warn("Invalid HTTP/2 upgrade! [got: " + _h2_header + "]");
			return null;
		}
		is.skip(8); // Skip the \r\nSM\r\n\r\n
		final IOContainer container = new IOContainer(socket, is, os);
		ServerThreadUtils.http2Initialization(container, hrv, rqd);
		IOUtils.closeAllQuietly(is, os, socket);

		return protocol;
	}

	protected void __pri_http2(final OutputStream os, final InputStream is, final Socket socket) throws Exception {
		is.skip(8);
		final IOContainer container = new IOContainer(socket, is, os);
		ServerThreadUtils.http2Initialization(container, hrv, rqd);
		IOUtils.closeAllQuietly(is, os, socket);
	}
}
